/*
 * GlobalChecker.h
 *
 *  Created on: 2014. 8. 5.
 *      Author: mega
 */

#ifndef GLOBALCHECKER_H_
#define GLOBALCHECKER_H_

#include "Static.h"
#include "Function.h"
#include "NResource/Static.h"
#include "GuildRank.h"

#include <Dispatcher/Static.h>




namespace GuildServer {

class GlobalChecker
{
public:
	GlobalChecker()
	{
		m_pAttendanceTimer = new ::Dispatcher::Timer();

		time_t checkTime = GetAttendanceCheckTime();
		int remainSec = 0;

		if (true == Static::Instance().GetTest())
			remainSec = (checkTime + (60 * 20)) - time(NULL);
		else
			remainSec = (checkTime + (60 * 60 * 24)) - time(NULL);

		SetAttendanceTimer(1000 * remainSec);

		LOG(DEV, __FUNCTION__, " : AttendanceTimer remain : ", remainSec);
	}

	virtual ~GlobalChecker()
	{
		delete m_pAttendanceTimer;
	}

public:
	void	OnAttendanceTimer()
	{
		time_t checkTime = 0;

		if (true == Static::Instance().GetTest())
		{
			checkTime = time(NULL) - (60 * 20);
			SetAttendanceTimer(1000 * 60 * 20);
		}
		else
		{
			checkTime = time(NULL) - (60 * 60 * 24);
			SetAttendanceTimer(1000 * 60 * 60 * 24);
		}

		LOG(DEV, __FUNCTION__, " : CheckTime : ", checkTime);

		NResource::ResourceGuildBanalce * pBalance = NResource::Static::Instance().GetGuildBalance();
		if (NULL == pBalance)
		{
			LOG(ERR, __FUNCTION__, " : pBalance is NULL");
			return;
		}

		// 길드원 미접속 점수
		int notConnectpoint = 0;
		{
			NResource::ResourceGuildBanalce::Flyweight * pFly = pBalance->GetFly(GUILD_NOT_CONNECT_POINT);
			if (NULL == pFly)
			{
				LOG(ERR, __FUNCTION__, " : pFly(GUILD_NOT_CONNECT_POINT) is NULL");
				return;
			}

			notConnectpoint = pFly->_VALUE;
		}

		int dailyMaxScore = pBalance->GetMemberDailyMaxScore();
		if (0 >= dailyMaxScore)
		{
			LOG(ERR, __FUNCTION__, " : member daily max score get fail.");
			return;
		}


		::GuildServer::GuildRank& kGuildRank = ::GuildServer::Static::Instance().GetRankList();

		Static::GUILDMAP & clsGuildMap = Static::Instance().GetGuildMap();
		LOG(DEV, __FUNCTION__, " : guild count : ", clsGuildMap.size());

		auto guildIter = clsGuildMap.begin();
		for (; guildIter != clsGuildMap.end(); ++guildIter)
		{
			std::shared_ptr<Guild>	pGuild = guildIter->second;

			Guild::MEMBERTREE & clsMemberMap = pGuild->GetMemberTree();

			LOG(DEV, __FUNCTION__, " : Guild_seq : ", pGuild->GetSeq(), " Member_Count : ", clsMemberMap.size());

			// 출석 체크 주기내에 접속하지 않은 길드원 수
			int userCount = 0;

			auto memberIter = clsMemberMap.begin();
			for (; memberIter != clsMemberMap.end(); ++memberIter)
			{
				std::shared_ptr<Member> pMember = memberIter->second;

				// 접속한 유저는 SKIP
				if (0 < pMember->GetData()._serverid)
					continue;

				// 주기내에 접속한 유저는 SKIP
				if (checkTime <= pMember->GetData()._loginTime)
					continue;

				userCount++;

				if (0 >= pMember->GetData()._contributeScore
						&& 0 >= pMember->GetData()._dailyScore)
				{
					continue;
				}

				// 출석 체크 주기내에 접속을 하지 않은 경우 포인트 차감
				pMember->ChangeMemberScore(notConnectpoint, dailyMaxScore);
				pMember->SetMemberFlushDB(true);
			}

			if (1 <= userCount)
			{
				// 길드 포인트 차감
				int decreasePoint = notConnectpoint * userCount;
				pGuild->ChangeScore(decreasePoint);
				pGuild->SetFlushDB(true);
				pGuild->SetTimer();

				pGuild->UpdateGradeDown();
			}

			// 이전 랭킹/포인트 저장
			kGuildRank.SaveDailySnapshot( pGuild->GetSeq(), pGuild->GetData()._score );
		}
	}

	void	SetAttendanceTimer(int tick)
	{
		m_pAttendanceTimer->SetTimer(tick, std::bind(&GlobalChecker::OnAttendanceTimer, this));
	}

private:
	::Dispatcher::Timer * m_pAttendanceTimer;
};

} /*GuildServer*/


#endif /* GLOBALCHECKER_H_ */
